package a_12_28introspector;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * 反射是在运行状态,可以动态的获取类的所有的属性以及动态调用任意一个方法，强调的是运行状态。
 * <p>
 * <p>
 * 内省(IntroSpector)是Java 语言对 Bean 类属性、事件的一种缺省处理方法。
 * <p>
 * JavaBean是一种特殊的类，主要用于传递数据信息，这种类中的方法主要用于访问私有的字段，
 * 且方法名符合某种命名规则。
 * <p>
 * 如果在两个模块之间传递信息，可以将信息封装进JavaBean中，
 * 这种对象称为“值对象”(Value Object)，或“VO”。
 * 方法比较少。这些信息储存在类的私有变量中，通过setName()、getName()获得。
 * <p>
 * 内省机制是通过反射来实现的，BeanInfo用来暴露一个bean的属性、方法和事件，
 * 以后我们就可以操纵该JavaBean的属性。
 *
 *
 *
 *  * --通过内省api来组装一个对象，bean对象的属性是通过对象的配置文件来获取的
 *  * --符合程序设计：高内聚，低耦合的原则和开闭原则（对修该关闭，对扩展开放）
 *  * --案例：与代码解耦，利于代码维护（只需要通过配置文件实现修改）
 */
public class BeanFactory {

    private static Properties properties = new Properties();

    //静态代码块
    static {
        InputStream inputStream = Thread
                .currentThread()
                .getContextClassLoader()
                .getResourceAsStream("a_12_28introspector\\config.properties");

        try {
            properties.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    public static Object getBean(String className) throws Exception {
        Object bean = null;

        //内省机制是通过反射来实现的
        Class aClass = Class.forName(className);
        bean = aClass.newInstance();
        //通过类信息获取bean的描述
        BeanInfo beanInfo = Introspector.getBeanInfo(aClass);
        //获取bean的【属性】信息描述器
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();

        for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
            //相当与set方法，获取设置属性值的方法
            Method writeMethod = propertyDescriptor.getWriteMethod();
            String propertyName = propertyDescriptor.getName();
            //System.out.println(name);
            if ("username".equals(propertyName)) {
                //调用属性的set方法
                writeMethod.invoke(bean, properties.getProperty("bean.username"));
            } else if ("password".equals(propertyName)) {
                //调用属性的set方法
                writeMethod.invoke(bean, properties.getProperty("bean.password"));
            } else if ("url".equals(propertyName)) {
                //调用属性的set方法
                writeMethod.invoke(bean, properties.getProperty("bean.url"));
            }



        }


        return bean;
    }


    public static void main(String[] args) throws  Exception{
        Object bean = getBean(properties.getProperty("bean.name"));
        System.out.println(bean.toString());
    }
}
